package com.baoteng.rbspy.interceptor.cookie;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;

public class OKHttpCookieJar implements CookieJar {

	private final Logger logger = LoggerFactory.getLogger(OKHttpCookieJar.class);

	private final Map<String, List<Cookie>> serverCookieStore = new ConcurrentHashMap<String, List<Cookie>>();

	private Map<String, List<Cookie>> clientCookieStore = new ConcurrentHashMap<String, List<Cookie>>();

	private OKHttpCookieJar() {

	}

	private static class OKHttpCookieJarHolder {
		private static final OKHttpCookieJar handler = new OKHttpCookieJar();
	}

	private static OKHttpCookieJar newInstance() {
		return OKHttpCookieJarHolder.handler;
	}

	public static final class Builder {

		OKHttpCookieJar cookieJar=OKHttpCookieJar.newInstance();

		private void putCookie(List<Cookie> storedCookieList, Cookie newCookie) {

			Cookie oldCookie = null;
			for (Cookie storedCookie : storedCookieList) {

				final String oldCookieKey = storedCookie.name() + storedCookie.path();
				final String newCookieKey = newCookie.name() + newCookie.path();

				if (oldCookieKey.equals(newCookieKey)) {
					oldCookie = storedCookie;
					break;
				}
			}
			if (oldCookie != null) {
				storedCookieList.remove(oldCookie);
			}
			storedCookieList.add(newCookie);
		}

		private void removeCookie(HttpUrl httpUrl) {
			final String host = httpUrl.host();
			cookieJar.clientCookieStore.remove(host);
			cookieJar.serverCookieStore.remove(host);
		}

		private void setCookie(String url, Cookie cookie) {

			final String host = HttpUrl.parse(url).host();

			List<Cookie> cookieListForUrl = cookieJar.clientCookieStore.get(host);
			if (cookieListForUrl == null) {
				cookieListForUrl = new ArrayList<Cookie>();
				cookieJar.clientCookieStore.put(host, cookieListForUrl);
			}
			putCookie(cookieListForUrl, cookie);

		}

		public Builder addCookie(String url, String cookieName, String cookieValue) {
			final HttpUrl httpUrl = HttpUrl.parse(url);
			setCookie(url, Cookie.parse(httpUrl, cookieName + "=" + cookieValue));
			return this;
		}

		public Builder addCookie(HttpUrl httpUrl, String cookieName, String cookieValue) {
			setCookie(httpUrl.host(), Cookie.parse(httpUrl, cookieName + "=" + cookieValue));
			return this;
		}

		public Builder removeCookie(String url) {
			removeCookie(HttpUrl.parse(url));
			return this;
		}

		public OKHttpCookieJar build() {
			return this.cookieJar ;
		}

	}

	public Map<String, List<Cookie>> getmClientCookieStore() {
		return clientCookieStore;
	}

	public void setmClientCookieStore(Map<String, List<Cookie>> clientCookieStore) {
		this.clientCookieStore = clientCookieStore;
	}

	public Map<String, List<Cookie>> getmServerCookieStore() {
		return serverCookieStore;
	}

	@Override
	public List<Cookie> loadForRequest(HttpUrl url) {

		List<Cookie> serverCookieList = serverCookieStore.get(url.host());

		if (serverCookieList == null) {
			serverCookieList = new ArrayList<Cookie>();
		}

		final List<Cookie> _clientCookieStore = clientCookieStore.get(url.host());

		if (_clientCookieStore != null) {
			serverCookieList.addAll(_clientCookieStore);
		}
		
		return serverCookieList != null ? serverCookieList : new ArrayList<Cookie>();
	}

	@Override
	public void saveFromResponse(HttpUrl url, List<Cookie> unmodifiableCookieList) {
		try {
			List<Cookie> cookies = serverCookieStore.get(url.host());
			if (cookies != null) {
				List<Cookie> _cookies = cookies.stream().filter(cookie->{
					logger.info("saveFromResponse serverCookieStore cokkie :{}",ReflectionToStringBuilder.toString(cookie));
					boolean isAdd = true;
					for(Cookie _cookie : unmodifiableCookieList) {
						logger.info("saveFromResponse unmodifiableCookieList cokkie :{}",ReflectionToStringBuilder.toString(_cookie));
						if (cookie.name().equals(_cookie.name()) && cookie.domain().equals(_cookie.domain()) && cookie.path().equals(_cookie.path()) && !cookie.value().equals(_cookie.value())) {
							isAdd = false;
						}
					}
					return isAdd;
				}).collect(Collectors.toList());
				_cookies.addAll(unmodifiableCookieList);
				serverCookieStore.put(url.host(),_cookies);
//				List<Cookie> _cookies = unmodifiableCookieList.stream().filter(cookie -> {
//					logger.info("saveFromResponse unmodifiableCookieList cokkie :{}",ReflectionToStringBuilder.toString(cookie));
//					boolean isAdd = true;
//					for (Cookie _cookie : cookies) {
//						logger.info("saveFromResponse serverCookieStore cokkie :{}",ReflectionToStringBuilder.toString(_cookie));
//						if (cookie.name().equals(_cookie.name()) && cookie.domain().equals(_cookie.domain()) && cookie.path().equals(_cookie.path())) {
//							isAdd = false;
//						}
//					}
//					return isAdd;
//				}).collect(Collectors.toList());
//				cookies.addAll(_cookies);
			} else {
				serverCookieStore.put(url.host(), new ArrayList<Cookie>(unmodifiableCookieList));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
